`timescale 1ns/1ns
`define DATA_WIDTH 256

module Register(input clk,
				input rst_n,
				input curve_sel,
				input re_t1,
				input re_t7,
				input [21:0] r_sel,
				input [`DATA_WIDTH-1:0] mul_c,
				input [`DATA_WIDTH-1:0] add_c,
				input [`DATA_WIDTH-1:0] inv_c,
				//input [`DATA_WIDTH-1:0] a,
				input [`DATA_WIDTH-1:0] x1,
				input [`DATA_WIDTH-1:0] y1,
				input [`DATA_WIDTH-1:0] Hv_r,
				input [`DATA_WIDTH-1:0] r,
				input [`DATA_WIDTH-1:0] ss,
				input [`DATA_WIDTH-1:0] s,
				input [`DATA_WIDTH-1:0] k1,
				input [`DATA_WIDTH-1:0] kg_y,
				input [`DATA_WIDTH-1:0] k,
				input MM_end_flag,
				output reg [`DATA_WIDTH-1:0] T0,
				output reg [`DATA_WIDTH-1:0] T1,
				output reg [`DATA_WIDTH-1:0] T2,
				output reg [`DATA_WIDTH-1:0] T3,
				output reg [`DATA_WIDTH-1:0] T4,
				output reg [`DATA_WIDTH-1:0] T5,
				output reg [`DATA_WIDTH-1:0] T6,
				output reg [`DATA_WIDTH-1:0] T7
			   );

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T0 <= `DATA_WIDTH'd0;
	else
		case(r_sel[1:0])
			2'b01 : T0 <= add_c;
			/*2'b10 : 
					if(MM_end_flag)
					T0 <= mul_c;
					else
					T0 <= T0;
			*/
			2'b11 : if(curve_sel == 1'b0)
						T0 <= 256'hffffffff00000001000000000000000000000000fffffffffffffffffffffffc;//256r1 a
					else
						T0 <= 256'hFFFFFFFE_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_00000000_FFFFFFFF_FFFFFFFC;//sm2 a
			default : T0 <= T0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T1 <= `DATA_WIDTH'd0;
	else
		case(r_sel[4:2])
			3'b001 : T1 <= add_c;
			3'b010 :
					if(MM_end_flag)
					T1 <= mul_c;
					else
					T1 <= T1;
			3'b011 : if(re_t1)
					 T1 <= `DATA_WIDTH'd0;
					 else
					 T1 <= s;
			3'b100 : T1 <= x1;
			3'b101 : T1 <= Hv_r;
			3'b110 : T1 <= k1;
			3'b111 : T1 <= T4;
			default : T1 <= T1;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T2 <= `DATA_WIDTH'd0;
	else
		case(r_sel[7:5])
			3'b001 : T2 <= add_c;
			3'b010 : 
					if(MM_end_flag)
					T2 <= mul_c;
					else
					T2 <= T2;
			3'b011 : T2 <= kg_y;
			3'b100 : T2 <= y1;
			3'b101 : T2 <= r;
			3'b111 : T2 <= T5;
			default : T2 <= T2;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T3 <= `DATA_WIDTH'd0;
	else
		case(r_sel[10:8])
			3'b001 : T3 <= add_c;
			3'b010 : 
					if(MM_end_flag)
					T3 <= mul_c;
					else
					T3 <= T3;	
			3'b011 : T3 <= x1;
			3'b100 : T3 <= `DATA_WIDTH'd1;
			3'b111 : T3 <= inv_c;
			default : T3 <= T3;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T4 <= `DATA_WIDTH'd0;
	else
		case(r_sel[13:11])
			3'b001 : T4 <= add_c;
			3'b010 : 
					if(MM_end_flag)
					T4 <= mul_c;
					else
					T4 <= T4;
			3'b011 : T4 <= T1;
			3'b100 : T4 <= k;
			3'b101 : T4 <= T3;
			default : T4 <= T4;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T5 <= `DATA_WIDTH'd0;
	else
		case(r_sel[16:14])
			3'b001 : T5 <= add_c;
			3'b010 : 
					if(MM_end_flag)
					T5 <= mul_c;
					else
					T5 <= T5;
			3'b011 : T5 <= T2;
			3'b100 : T5 <= T7;
			default : T5 <= T5;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T6 <= `DATA_WIDTH'd0;
	else
		case(r_sel[18:17])
			2'b01 : T6 <= add_c;
			2'b10 : 
					if(MM_end_flag)
					T6 <= mul_c;
					else
					T6 <= T6;
			2'b11 : T6 <= y1;
			default : T6 <= T6;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		T7 <= `DATA_WIDTH'd0;
	else
		case(r_sel[21:19])
			3'b001 : T7 <= add_c;
			3'b010 : 
					if(MM_end_flag)
					T7 <= mul_c;
					else
					T7 <= T7;
			3'b011 : if(re_t7)
					T7 <= `DATA_WIDTH'd0;
					else
					T7 <= ss;
			3'b100 : T7 <= y1;
			default : T7 <= T7;
		endcase
end

endmodule